﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Resources;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Media;
using PokeData;

namespace PokeTD {
    class MapSelectionScreen : MenuScreen {

        ContentManager content;
        Texture2D previewbg;

        private List<Map> AvailableMaps = new List<Map>();
        public MapSelectionScreen()
            : base("") {

        }

        public override void Activate(bool instancePreserved) {
            base.Activate(instancePreserved);
            if (!instancePreserved) {
                if (content == null)
                    content = new ContentManager(ScreenManager.Game.Services, "Content");

                FindMaps();
                foreach (Map map in AvailableMaps) {
                    MenuEntry mapEntry = new MenuEntry(map.Name);
                    mapEntry.Selected += MapEntrySelected;
                    MenuEntries.Add(mapEntry);
                }
                previewbg = new Texture2D(ScreenManager.GraphicsDevice, 1, 1);
                previewbg.SetData<Color>(new Color[] { Color.White });
            }
        }

        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void Unload() {
            content.Unload();
        }

        /// <summary>
        /// Event handler for when the Play Game menu entry is selected.
        /// </summary>
        void MapEntrySelected(object sender, EventArgs e) {
            MediaPlayer.Stop();
            Globals.mediaPlaying = false;
            LoadingScreen.Load(ScreenManager, true, new GameplayScreen(AvailableMaps[SelectedEntry]));
        }

        /// <summary>
        /// Sucht nach Maps
        /// </summary>
        /// <param name="directory">Ordner, in dem zu suchen ist</param>
        /// <returns>Liste mit Pfadnamen</returns>
        private void FindMaps(string directory) {
            DirectoryInfo dir = new DirectoryInfo(directory);
            if (!dir.Exists)
                return;

            
            FileInfo[] files = dir.GetFiles("*.map", SearchOption.AllDirectories);
            foreach (FileInfo file in files) {
                List<Texture2D> worldTextures = loadTileset(file.FullName);
                Map m = new Map(new Vector2(0, 0), worldTextures, file.FullName);
                if (m.DefaultPath.Count > 0) {
                    AvailableMaps.Add(m);
                }
            }
        }

        /// <summary>
        /// Sucht nach allen Maps
        /// </summary>
        private void FindMaps() {
            // Map-Ordner (standard-Maps)
            FindMaps("Maps");

            // Custom Maps (Eigene Dateien/PokeTD/Maps)
            FindMaps(Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\PokeTD\Maps");
        }

        private List<Texture2D> loadTileset(string path) {
            Dictionary<string, Texture2D> tileset = new Dictionary<string, Texture2D>();
            ResourceReader resr = new ResourceReader(path);
            IDictionaryEnumerator en = resr.GetEnumerator();
            byte[] texture;
            while (en.MoveNext()) {
                string type;
                string key = (string)en.Key;
                resr.GetResourceData(key, out type, out texture);
                if (type.Equals("png")) {
                    MemoryStream ms = new MemoryStream(texture);
                    tileset.Add(key, Texture2D.FromStream(ScreenManager.GraphicsDevice, ms, 32, 32, true));
                }
            }
            List<Texture2D> tilesetSorted = new List<Texture2D>();
            for (int i = 0; i < tileset.Count; i++) {
                tilesetSorted.Add(tileset["" + i]);
            }
            return tilesetSorted;
        }

        #region Update and Draw
        protected override void UpdateMenuEntryLocations() {
            float transitionOffset = (float)Math.Pow(TransitionPosition, 2);

            Vector2 position = new Vector2(0f, 300f);
            for (int i = 0; i < MenuEntries.Count; i++) {
                MenuEntry menuEntry = MenuEntries[i];

                // each entry is to be centered horizontally
                position.X = 30;

                if (ScreenState == ScreenState.TransitionOn)
                    position.X -= transitionOffset * 256;
                else
                    position.X += transitionOffset * 512;

                // set the entry's position
                menuEntry.Position = position;

                // move down for the next entry the size of this entry
                position.Y += menuEntry.GetHeight(this);
            }
        }

        /// <summary>
        /// Draws the menu.
        /// </summary>
        public override void Draw(GameTime gameTime) {
            if (IsActive) {

                GraphicsDevice graphics = ScreenManager.GraphicsDevice;
                SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
                int entryWidth = 0;
                foreach (MenuEntry entry in MenuEntries) {
                    int temp = entry.GetWidth(this);
                    if (temp > entryWidth) entryWidth = temp;
                }
                Texture2D tex = AvailableMaps[SelectedEntry].DrawToTexture(graphics);
                float heightscale = (float)tex.Height / (float)(graphics.Viewport.Height - 310);
                float widthscale = (float)tex.Width / (float)(graphics.Viewport.Width - 75 - entryWidth);
                int scale = (int)Math.Ceiling(Math.Max(widthscale, heightscale));
                Rectangle bg = new Rectangle(graphics.Viewport.Width - (tex.Width / scale) - 31, 299, tex.Width / scale + 2, tex.Height / scale + 2);
                
                spriteBatch.Begin();

                spriteBatch.Draw(previewbg, bg, Color.Black);
                spriteBatch.Draw(tex, new Rectangle(graphics.Viewport.Width - (tex.Width / scale) - 30, 300, tex.Width / scale, tex.Height / scale), Color.White);
                //spriteBatch.Draw(tex, new Rectangle(graphics.Viewport.Width - ((int)(200.0 / tex.Height * tex.Width)) - 10, 300, (int)(200.0 / tex.Height * tex.Width), 200), Color.White);
                
                spriteBatch.End();
            }
            base.Draw(gameTime);
        }
        #endregion
    }
}
